#ifndef BEAUTYSTREAMER_BSPACKER_H
#define BEAUTYSTREAMER_BSPACKER_H

#include <cstdlib>
#include <vector>
#include <unordered_map>
#include <string>
#include <iostream>

#pragma pack(push, 1)
typedef struct {
	uint16_t headerSize;
	uint16_t nameSize;
	uint32_t offset;
	uint32_t size;
	char name[0];
} BSPackEntry;
#pragma pack(pop)

class BSPacker {
public:
    ~BSPacker();

    static BSPacker *create(std::string path);

    static BSPacker *load(std::string path);

    bool add(std::string filename, std::string entryName);

    bool writeOut();

    BSPackEntry *get(std::string entryName);

    // do not forget to free
    char *read(std::string entryName);

    bool pack(std::string dirname);

    bool unpack(std::string dirname);


protected:
    explicit BSPacker(const std::string &path, bool isCreate);

    std::vector<std::string> listFiles(const std::string &dirname, const std::string &basename = "");

    uint32_t fileSize(const std::string &filename);

    bool loadFile(const std::string &path);

    std::string getDirname(const std::string &filename);

    bool dirExists(const std::string &dirname);

    bool ensureDir(const std::string &dirname);


    std::vector<BSPackEntry *> m_entries;
    std::unordered_map<std::string, BSPackEntry *> m_entriesMap;

    std::vector<std::string> m_files;
    std::string m_path;
    bool m_isCreate;
    bool m_hasWriteOut;

    uint32_t m_lastOffset;
    uint32_t m_lastSize;
    uint32_t m_totalHeaderSize;

};


#endif //BEAUTYSTREAMER_BSPACKER_H
